// skin_client.c
#include "skin.h"
#include "skin_control.h"

PSKIN_CLIENT skin_add_control(PSKIN_WINDOW wnd, PSKIN_CLIENT control);
PSKIN_CLIENT skin_remove_control(PSKIN_WINDOW wnd, PSKIN_CLIENT control);

PSKIN_CLIENT skin_create_control(PSKIN_WINDOW pwnd, int object_type, int x, int y, int cx, int cy, int client_id, const char* object_name)
{
		if (pwnd)
		{
			PSKIN_CLIENT p = 0;
			switch (object_type)
			{
				case CONTROL_STATIC:	// static control
					p = (PSKIN_CLIENT) malloc(sizeof(SKIN_STATIC));
					memset(p, 0, sizeof(SKIN_STATIC));
					break;
				case CONTROL_BUTTON:	// button control
					p = (PSKIN_CLIENT) malloc(sizeof(SKIN_BUTTON));
					memset(p, 0, sizeof(SKIN_BUTTON));
					break;
				case CONTROL_PROGRESS:
					break;
				case CONTROL_SLIDE:
					break;
				case CONTROL_COMBOBOX:
				case CONTROL_LISTBOX:
				case CONTROL_LIST:
				case CONTROL_TREE:
				case CONTROL_EDIT:				
				case CONTROL_GAUGE:
				default:
					break;
			}
			if (p)
			{
				SDL_Rect rect;				
				if (object_name) 
					strcpy(p->name, object_name);
				p->rect.x 		= x;
				p->rect.y 		= y;
				p->rect.cx 		= x + cx;
				p->rect.cy 		= y + cy;
				p->client_type 	= object_type;
				p->parent		= pwnd;
				p->client_id	= client_id;
				skin_add_control(pwnd, p);

				// client bitmp
				p->client_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, cx, cy, 32, rmask, gmask, bmask, amask);

				// set default color
				rect.x = rect.y = 0;
				rect.w = cx;
				rect.h = cy;

				SDL_FillRect(p->client_surface, &rect, SDL_MapRGB(p->client_surface->format, 128, 128, 128));

				// set interfaces
				SKIN_OVERRIDE(p, OnPaint, 			skin_control_onpaint);
				SKIN_OVERRIDE(p, OnKeyDown,         skin_control_onkeydown);
        		SKIN_OVERRIDE(p, OnKeyUp,           skin_control_onkeyup);
        		SKIN_OVERRIDE(p, OnMouseMove, 		skin_control_onmousemove);
				SKIN_OVERRIDE(p, OnMouseButtonDown, skin_control_onmousebuttondown);
        		SKIN_OVERRIDE(p, OnMouseButtonUp,   skin_control_onmousebuttonup);
        		switch (object_type)
				{
					case CONTROL_STATIC:	// static control
						{
							PSKIN_STATIC s = (PSKIN_STATIC) p;
							s->foreground_color.r = s->foreground_color.g = s->foreground_color.b = 0;
							s->background_color.r = s->background_color.g = s->background_color.b = 128;
							SKIN_OVERRIDE(p, OnPaint, 			skin_static_onpaint);
						}
						break;
					case CONTROL_BUTTON:	// button control
						SKIN_OVERRIDE(p, OnMouseMove, 		skin_button_onmousemove);
						SKIN_OVERRIDE(p, OnMouseButtonDown, skin_button_onmousebuttondown);
		        		SKIN_OVERRIDE(p, OnMouseButtonUp,   skin_button_onmousebuttonup);
						break;					
					case CONTROL_COMBOBOX:
					case CONTROL_LISTBOX:
					case CONTROL_LIST:
					case CONTROL_TREE:
					case CONTROL_EDIT:
					default:						
						break;
				}				
				// initialize control
				p->OnPaint(p);
				return p;
			}
		}
		return 0;
}

int			skin_close_control(PSKIN_CLIENT p, int option)
{
	if (p)
	{
		switch (p->client_type)
		{
			case CONTROL_STATIC:	// static control
				{
					PSKIN_STATIC s = (PSKIN_STATIC) p;
					if (s->text_surface)
					{
						SDL_FreeSurface(s->text_surface);
						s->text_surface = 0;
					}
					printf("Control.Static.Close(type(%d))\r\n", p->client_type);
				}
				break;
			case CONTROL_BUTTON:	// button control
				{
					PSKIN_BUTTON button = (PSKIN_BUTTON) p;
					printf("normal release\r\n");
					if (button->normal)
					{
						SDL_FreeSurface(button->normal);
						button->normal = 0;
					}
					printf("hover release\r\n");
					if (button->hover)
					{
						SDL_FreeSurface(button->hover);
						button->hover = 0;
					}
					printf("clicked release\r\n");
					if (button->clicked)
					{
						SDL_FreeSurface(button->clicked);
						button->clicked = 0;
					}
					printf("Control.Button.Close(type(%d))\r\n", p->client_type);
				}
				break;
			case CONTROL_COMBOBOX:
			case CONTROL_LISTBOX:
			case CONTROL_LIST:
			case CONTROL_TREE:
			case CONTROL_EDIT:
			default:
				printf("Control.Close(type(%d))\r\n", p->client_type);
				break;
		}		
		if (p->client_surface)
		{
			SDL_FreeSurface(p->client_surface);
			p->client_surface = 0;
		}
		if (option)
		{
			skin_remove_control((PSKIN_WINDOW) p->parent, p);
		}
		free(p);
	}
	return 0;
}

PSKIN_CLIENT skin_add_control(PSKIN_WINDOW wnd, PSKIN_CLIENT control)
{
	if (wnd)
	{
		if (!wnd->clients)
		{
			wnd->clients = control;
			wnd->last_client = control;
		}
		else
		{
			PSKIN_CLIENT p = wnd->clients;
			while (p->next)
			{
				p = p->next;
			}
			if (p)
			{
				p->next = control;
				control->prev = p;
				wnd->last_client = control;
			}
		}
	}
	return control;
}

PSKIN_CLIENT skin_remove_control(PSKIN_WINDOW wnd, PSKIN_CLIENT control)
{
	if (wnd)
	{
		PSKIN_CLIENT p = wnd->clients;
		if (p == control)
		{
			wnd->clients = control->next;
			if (wnd->last_client == control)
			{
				wnd->last_client = 0;
			}
			control->next = 0;
			control->prev = 0;
		}
		else
		{
			while (p->next != 0 && p->next != control)
			{
				p = p->next;
			}
			if (p && p->next == control)
			{
				p->next = control->next;
				if (control->next)
				{
					PSKIN_CLIENT n = (PSKIN_CLIENT) control->next;
					n->prev = p;
				}
				if (wnd->last_client == control)
				{
					wnd->last_client = control->prev;
				}
				control->next = 0;
				control->prev = 0;
			}
		}
	}
	return control;
}

void		 skin_control_removeall(PSKIN_WINDOW wnd)
{
	PSKIN_CLIENT p = 0;
	PSKIN_CLIENT next = 0;
	if (wnd)
	{
		p = wnd->clients;
		while (p)
		{
			next = (PSKIN_CLIENT) p->next;
			skin_close_control(p, CONTROL_CLOSE_FORCED); // forced remove
			p = next;
		}
		wnd->clients = 0;
	}
}

PSKIN_CLIENT skin_control_move(PSKIN_CLIENT control, int x, int y, int cx, int cy, int option)
{
	if (control)
	{
		if ((control->rect.cx - control->rect.x) != cx ||
			(control->rect.cy - control->rect.y) != cy)
		{
			PSKIN_WINDOW pwnd = (PSKIN_WINDOW) control->parent;
			if (control->client_surface)
			{
				SDL_FreeSurface(control->client_surface);
				control->client_surface = 0;
			}
			control->client_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, cx, cy, 32, rmask, gmask, bmask, amask);			
		}
		control->rect.x = x;
		control->rect.y = y;
		control->rect.cx = x + cx;
		control->rect.cy = y + cy;
		control->OnPaint(control);
	}
	return control;
}

PSKIN_CLIENT skin_control_update(PSKIN_CLIENT control)
{
	if (control)
	{
		control->OnPaint(control);
	}
	return control;
}

// control events
int 		skin_control_onpaint(void* self)
{
	printf("Control.OnPaint()\r\n");
	return 0;
}

// keyboard
int         skin_control_onkeydown       (void* self, SDL_Event* e)
{
    PSKIN_WINDOW p = (PSKIN_WINDOW) self;
#if (SKIN_DEBUG == 1)
    printf("Control.OnKeyDown(type(%d), which(%d), state(%d), keysym(scancode(%d), sym(%d), mod(%d)))\r\n",  e->key.type,     
                                                                                                     e->key.which,
                                                                                                     e->key.state,
                                                                                                     e->key.keysym.scancode,
                                                                                                     e->key.keysym.sym,
                                                                                                     e->key.keysym.mod);
#endif
    return 0;
}

int         skin_control_onkeyup          (void* self, SDL_Event* e)
{
    PSKIN_WINDOW p = (PSKIN_WINDOW) self;
#if (SKIN_DEBUG == 1)
    printf("Control.OnKeyUp(type(%d), which(%d), state(%d), keysym(scancode(%d), sym(%d), mod(%d)))\r\n", e->key.type,       
                                                                                                  e->key.which,
                                                                                                  e->key.state,
                                                                                                  e->key.keysym.scancode,
                                                                                                  e->key.keysym.sym,
                                                                                                  e->key.keysym.mod);
#endif
    return 0;
}

int         skin_control_onmousemove(void* self, SDL_Event* e)
{
#if (SKIN_DEBUG == 1)
	printf("Control.OnMouseMove()\r\n");
#endif
	return 0;
}

int         skin_control_onmousebuttondown(void* self, SDL_Event* e)
{
    PSKIN_WINDOW p = (PSKIN_WINDOW) self;
#if (SKIN_DEBUG == 1)
    printf("Control.OnMouseButtonDown()\r\n");
#endif
    return 0;
}
int         skin_control_onmousebuttonup  (void* self, SDL_Event* e)
{
    PSKIN_WINDOW p = (PSKIN_WINDOW) self;
#if (SKIN_DEBUG == 1)
    printf("Control.OnMouseButtonUp()\r\n");
#endif
    return 0;
}

int 		skin_draw_controls(PSKIN_WINDOW pwnd)
{
	SDL_Rect rect;
	SDL_Rect src_rect;
	PSKIN_CLIENT p = 0;
	if (pwnd)
	{
		SDL_Surface* dst = pwnd->screen;
		SDL_Surface* src = 0;
		p = pwnd->clients;
		while (p)
		{
			src = p->client_surface;
			src_rect.x = src_rect.y = 0;
			src_rect.w = p->rect.cx - p->rect.x;
			src_rect.h = p->rect.cy - p->rect.y;
			rect.x = p->rect.x;
			rect.y = p->rect.y;
			rect.w = p->rect.cx;
			rect.h = p->rect.cy;

			SDL_BlitSurface(p->client_surface, &src_rect, pwnd->screen, &rect);

			p = p->next;
		}
	}
	return 0;
}